<?php
namespace Framework\Library\Component;

use Framework\Library\Core\Entity;

/**
 * 文件实体
 *
 * 数据表结构
 * CREATE  TABLE `your_database`.`table_name` (
 * `id` INT NOT NULL ,
 * `name` VARCHAR(255) NOT NULL ,
 * `package` VARCHAR(255) NOT NULL ,
 * `type` VARCHAR(255) NOT NULL ,
 * `size` INT NOT NULL ,
 * `create_time` DATETIME NOT NULL ,
 * `update_time` DATETIME NOT NULL ,
 * PRIMARY KEY (`id`) )
 * ENGINE = MyISAM
 * COMMENT = 'FileSystem组件数据表';
 *
 * 配置项：
 * 数据库连接信息
 * 数据包存放目录
 *
 *
 * @author Canvas Kent
 */
class FileEntity extends Entity{
	
	function __construct($module){
		
		parent::__construct($module,'file');
	
	}
	
	/**
	 * 使用PHP $_FILES['xxx']保存已上传文件到文件系统，并把文件信息记录到数据库，返回数据库记录标识
	 *
	 * 本方法在处理文件组时，具有事务性质，如果有一个文件无法正确处理，那么整组文件都会取消
	 *
	 * @param unknown $uploaded_file_info
	 * @return boolean|number|array
	 */
	public function save( $uploaded_file_info ){
	
		$file = $uploaded_file_info['tmp_name'];
	
		$datetime = $this->db->getNow();
	
		if (!is_array($file)){
				
			// 单个文件
				
			$des_file = $this->fs->savePackage($file);
				
			if ( $des_file ){
	
				$insert_id = $this->insertRecord(
						array(
								'name'=>$uploaded_file_info['name'],
								'package'=>$des_file,
								'type'=>$uploaded_file_info['type'],
								'size'=>$uploaded_file_info['size'],
								'create_time'=>$datetime,
								'update_time'=>$datetime
						)
				);
	
				if (!$insert_id){
						
					$this->deletePackage($des_file);
					return false;
						
				}else{
						
					return $insert_id;
						
				}
					
			}else return false;
				
		}else {
				
			// 文件组
				
			$insert_ids = array();
				
			for ($i = 0; $i < count($file); $i++){
	
				$f = $file[$i];
	
				$des_file = $this->fs->savePackage($f);
	
				if ( $des_file ){
	
					$insert_id = $this->insertRecord(
							array(
									'name'=>$uploaded_file_info['name'][$i],
									'package'=>$des_file,
									'type'=>$uploaded_file_info['type'][$i],
									'size'=>$uploaded_file_info['size'][$i],
									'create_time'=>$datetime,
									'update_time'=>$datetime
							)
					);
	
					if (!$insert_id){
							
						$this->fs->deletePackage($des_file); // 删除本文件已复制的数据包
						$this->delete($insert_ids); // 删除前面已保存的文件
						return false;
							
					}else{
							
						array_push($insert_ids,$insert_id);
							
					}
	
				}else return false;
	
			}
				
			return $insert_ids;
				
		}
	
	}
	
	public function update($file,$id=NULL){
		
		if (empty($id)&&empty($this->data)) throw new \Exception('缺少参数，或对象未激活，导致找不到要更新的目标对象');
		
		if (!empty($id)) $this->activate($id);
		
		// 保存新文件
		$package = $this->fs->savePackage($file['tmp_name']);
		if (!$package) throw new \Exception('上传新文件失败');
		
		$state = $this->fs->deletePackage($this->data['package']);
		if (!$state) {
			
			$this->fs->deletePackage($package);
			throw new \Exception('无法删除旧文件，更新失败');
		
		}
		
		// 更新文件成功，更新数据库文件记录
		$state = $this->updateRecord(array(
				'name'=>$file['name'],
				'package'=>$package,
				'type'=>$file['type'],
				'size'=>$file['size'],
				'update_time'=>$this->db->getNow()
		));
		
		if (!$state){
			
			$this->fs->deletePackage($package);
			throw new \Exception('更新数据库时失败，导致整个文件更新事务失败');
			
		}else return true;
		
	}
	
	/**
	 * 删除已保存的文件，包括文件包与数据库记录
	 * @param int|array $file_id
	 */
	public function delete( $file_id ){
	
		$datas = $this->selectRecord($file_id);
	
		if ( !empty($datas) ){
				
			foreach ($datas as $data){
	
				$this->fs->deletePackage($data['package']);
	
			}
				
			if ($this->deleteRecord($file_id)) return true;
			else throw new \Exception('删除文件的数据库记录失败');
				
		}
	
	}
	
	public function echoBin($id =NULL){
		
		if (empty($id)&&empty($this->data)) throw new \Exception('对象未激活，没有数据可用作输出');
		
		if (!empty($id)) $this->activate($id);
		
		Header("Content-type: ".$this->data['type']);
		Header("Accept-Ranges: bytes");
		Header("Accept-Length: ".$this->data['size']);
		Header("Content-Disposition: attachment; filename=".$this->data['name']);
		
		echo $this->fs->getPackage($this->data['package']);
		
	}
	
}